using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Cz
{
    public static class CzStringTool
    {
        public static string ReadString(this Stream stream)
        {
            using (var sr = new StreamReader(stream))
            {
                return sr.ReadToEnd();
            }
        }
        
        public static string Join<T>(this IEnumerable<T> list, string separator = ",")
        {
            if (!list.Any())
                return "";
            
            var sb = new StringBuilder();
            foreach (var val in list)
            {
                sb.Append(val);
                sb.Append(separator);
            }

            sb.Length -= separator.Length;
            return sb.ToString();
        }
        
        public static string ToJson(this object obj, bool showType = false, int space = 0)
        {
            switch (obj)
            {
                case null:
                    return "null";
                case DateTime _:
                case string _:
                    if(showType)
                        return $"[{obj.GetType().Name}]\"{obj}\"";
                    return $"\"{obj}\"";
                case Hashtable ht:
                {
                    var sb = new StringBuilder();
                    AddLineSpace(sb, space);
                    if(showType)
                        sb.Append($"[{obj.GetType().Name}]");
                    sb.Append("{");
                    
                    if (ht.Count > 0)
                    {
                        foreach (var k in ht.Keys)
                        {
                            AddLineSpace(sb, space + 4);
                            sb.Append(k.ToJson(showType, space + 4) + ":" + ht[k].ToJson(showType, space + 4) + ",");
                        }

                        sb.Length --;
                    }

                    AddLineSpace(sb, space);
                    sb.Append("}");
                    return sb.ToString();
                }
                case IDictionary dict:
                {
                    var sb = new StringBuilder();
                    AddLineSpace(sb, space);
                    if(showType)
                        sb.Append($"[{obj.GetType().Name}]");
                    sb.Append("{");
                    foreach (var k in dict.Keys)
                    {
                        AddLineSpace(sb, space + 4);
                        sb.Append(k.ToJson(showType, space + 4) + ":" + dict[k].ToJson(showType, space + 4));
                    }
                    
                    AddLineSpace(sb, space);
                    sb.Append("}");
                    return sb.ToString();
                }
                case IList list:
                {
                    var sb = new StringBuilder();
                    AddLineSpace(sb, space);
                    if(showType)
                        sb.Append($"[{obj.GetType().Name}]");
                    sb.Append("[");
                    if (list.Count > 0)
                    {
                        foreach (var v in list)
                        {
                            sb.Append(v.ToJson(showType, space + 4) + ",");
                        }

                        sb.Length --;
                    }

                    AddLineSpace(sb, space);
                    sb.Append("]");
                    return sb.ToString();
                }
                case IEnumerable enumerable:
                {
                    var sb = new StringBuilder();
                    AddLineSpace(sb, space);
                    if(showType)
                        sb.Append($"[{obj.GetType().Name}]");
                    sb.Append("[");
                    foreach (var item in enumerable)
                    {
                        sb.Append(item.ToJson(showType, space + 4) + ",");
                    }

                    AddLineSpace(sb, space);
                    sb.Append("]");
                    return sb.ToString();
                }
                default:
                    if(showType)
                        return $"[{obj.GetType().Name}]" + obj;
                    return obj.ToString();
            }

            void AddLineSpace(StringBuilder builder, int count)
            {
                builder.AppendLine();
                for (var i = 0; i < count; i++)
                {
                    builder.Append(" ");
                }
            }
        }
    }
}